/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * NewJPanel.java
 *
 * Created on 01-Apr-2009, 16:59:18
 */

package edu.napier.soc.xfdm.uci;

import edu.napier.soc.xfdm.model.*;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Thomas
 */
public class EntityTypeView extends javax.swing.JPanel {

	private EntityType entityType;
	private List<RelationshipModel> relationships;

	/**
	 * Creates new form NewJPanel
	 *
	 * @param entityType
	 */
	public EntityTypeView(EntityType entityType) {
		initComponents();
		this.relationships = new LinkedList<RelationshipModel>();
		this.entityType = entityType;
		label.setText(entityType.getName());
		setTree(entityType.getFunctions(),
				entityType.getConstraints());
		int height = tree.getPreferredSize().height + 20;
		int width = tree.getPreferredSize().width + 20;
		setPreferredSize(new Dimension(width, height));
	}


	/**
	 * This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {

		label = new JLabel();
		tree = new JTree();

		setLayout(new BorderLayout());

		label.setHorizontalAlignment(SwingConstants.CENTER);
		add(label, BorderLayout.PAGE_START);

		tree.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
		tree.setRootVisible(false);
		tree.setSelectionModel(null);
		add(tree, BorderLayout.CENTER);
	}// </editor-fold>//GEN-END:initComponents

	public void setTree(List<Function> functions,
	                    List<Constraint> constraints) {
		DefaultMutableTreeNode treeNode1 =
				new DefaultMutableTreeNode("EntityType");
		DefaultMutableTreeNode treeNode2 =
				new DefaultMutableTreeNode("Functions");
		DefaultMutableTreeNode treeNode3 =
				new DefaultMutableTreeNode("Constraints");

		for (Function f : functions) {
			if (entityType.isSupertypeFunction(f)) {
				continue;
			}
			ReturnType r = f.getReturnType();

			if (r == ReturnType.ENTITY) {
				relationships.add(RelationshipModel.newInstance(f));
				continue;
			}
			String s = f.getName() + " - " + f.getReturnType();
			DefaultMutableTreeNode tn = new DefaultMutableTreeNode(s);
			treeNode2.add(tn);
		}

		EntityType supertype = entityType.getSupertype();
		if (supertype != null) {
			relationships.add(RelationshipModel.newSupertypeModel(supertype));
		}

		for (Constraint c : constraints) {
			String s = c.getName() + " - " + c.getConstraintType();
			DefaultMutableTreeNode tn = new DefaultMutableTreeNode(s);
			treeNode3.add(tn);
		}

		treeNode1.add(treeNode2);
		treeNode1.add(treeNode3);

		tree.setModel(new DefaultTreeModel(treeNode1));

		for (int i = 0; i < tree.getRowCount(); i++) {
			tree.expandRow(i);
		}
	}

	public EntityType getEntityType() {
		return entityType;
	}

	public List<RelationshipModel> getRelationships() {
		return relationships;
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private JLabel label;
	private JTree tree;
	// End of variables declaration//GEN-END:variables

	public static class RelationshipModel {

		public enum Cardinality {
			ONETOONE("1:1"), ONETOMANY("1:N"), SUPERTYPE("inherits");
			private final String name;

			Cardinality(String name) {
				this.name = name;
			}

			public String getName() {
				return name;
			}
		}

		private final EntityType e;
		private final Cardinality c;
		private final Function f;

		private RelationshipModel(Function f, EntityType e, Cardinality c) {
			this.e = e;
			this.c = c;
			this.f = f;
		}

		public static RelationshipModel newSupertypeModel(
				EntityType supertype) {
			return new RelationshipModel(null, supertype,
					Cardinality.SUPERTYPE);
		}

		public static RelationshipModel newInstance(Function f) {
			Cardinality c = f.isMultiValued()
					? Cardinality.ONETOMANY : Cardinality.ONETOONE;
			return new RelationshipModel(f,
					((EntityFunction) f).getEntityType(), c);
		}

		public EntityType getRelationshipTo() {
			return e;
		}

		public Cardinality getCardinality() {
			return c;
		}

		public Function getFunction() {
			return f;
		}
	}
}
